package hao.itheima.filter;

import hao.itheima.exception.BusinessException;
import hao.itheima.utils.CurrentHolder;
import hao.itheima.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;

//-------------------------------回见, 下次从这里写起
@Slf4j
@WebFilter("/*")
public class LoginCheckFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //0.强转对象, 获取url
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
        //1.获取url
        StringBuffer URL = httpServletRequest.getRequestURL();
        String URI = httpServletRequest.getRequestURI();
        //1.1输出路径
        log.info("url = {}", URL);  // 拼接成了字符串
        log.info("URI = {}", URI);
        //2.判断请求url中是否包含login, 如果包含, 说明登录操作,放行
        if (URI.contains("login")) {
            //放行
            filterChain.doFilter(servletRequest, servletResponse);
            //结束当前请求  --> 否则就是死循环了, 感慨是login是没有token的

            //[注意] 一定要结束当前请求, 不应该往下执行代码逻辑
            return;
        }
        //3.获取请求头中的令牌
        String token = httpServletRequest.getHeader("token");
        //4.判断令牌是否存在, 如果不存在, 相应401
        if (token == null) {
            //响应状态码
            httpServletResponse.setStatus(401);
            //日志输出
            log.error("令牌为空");
            //抛出异常
//            throw new BusinessException("未登录,请先登录");  -----> 不可以报这个异常, 否则,底层就会返回500, 不符合接口文档
            //[注意] 一定要结束当前请求, 不应该往下执行代码逻辑
            return;
        }
        //5.解析token, 如果解析失败, 相应401
        try {
            //开始解析, 如果解析失败,就会跑异常
            Claims claims = JwtUtils.parseJWT(token);
            //日志输出
            log.info("claims = {}", claims);

            //1.获取当前用户的id
            Integer empId = Integer.valueOf(claims.get("id").toString());
            //2.将获取到的id存储到当前线程的ThreadLocal当中
            CurrentHolder.setCurrentId(empId);
            //3.日志输出
            log.info("当前用户id:{}, 存储到ThreadLocal当中", empId);

        } catch (Exception e) {
            //设置状态码
            httpServletResponse.setStatus(401);
            //日志输出
            log.error("令牌解析失败:{}", e.getMessage()); // 要查看到错误信息, 不能让错误信息,被吃掉
//            throw new BusinessException("未登录, 请先登录");
            return;
        }
        //6.放行
        filterChain.doFilter(servletRequest, servletResponse);


        //4.最后进行删除资源
        CurrentHolder.remove(); // 删除资源

    }
}
